/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.ohosannotations.internal.core;

import org.ohosannotations.OhosAnnotationsEnvironment;
import org.ohosannotations.Option;
import org.ohosannotations.handler.AnnotationHandler;
import org.ohosannotations.internal.core.handler.AfterExtrasHandler;
import org.ohosannotations.internal.core.handler.AfterInjectHandler;
import org.ohosannotations.internal.core.handler.AfterPreferencesHandler;
import org.ohosannotations.internal.core.handler.AfterViewsHandler;
import org.ohosannotations.internal.core.handler.AnimationResHandler;
import org.ohosannotations.internal.core.handler.AppHandler;
import org.ohosannotations.internal.core.handler.BackgroundHandler;
import org.ohosannotations.internal.core.handler.BeanHandler;
import org.ohosannotations.internal.core.handler.BindingObjectHandler;
import org.ohosannotations.internal.core.handler.CheckedChangeHandler;
import org.ohosannotations.internal.core.handler.ClickHandler;
import org.ohosannotations.internal.core.handler.ColorResHandler;
import org.ohosannotations.internal.core.handler.ColorStateListResHandler;
import org.ohosannotations.internal.core.handler.ComponentByIdHandler;
import org.ohosannotations.internal.core.handler.ComponentsByIdHandler;
import org.ohosannotations.internal.core.handler.CustomTitleHandler;
import org.ohosannotations.internal.core.handler.DataBoundHandler;
import org.ohosannotations.internal.core.handler.DefaultResHandler;
import org.ohosannotations.internal.core.handler.EAbilityHandler;
import org.ohosannotations.internal.core.handler.EApplicationHandler;
import org.ohosannotations.internal.core.handler.EBeanHandler;
import org.ohosannotations.internal.core.handler.EFractionHandler;
import org.ohosannotations.internal.core.handler.EIntentServiceHandler;
import org.ohosannotations.internal.core.handler.EProviderHandler;
import org.ohosannotations.internal.core.handler.EReceiverHandler;
import org.ohosannotations.internal.core.handler.EServiceHandler;
import org.ohosannotations.internal.core.handler.EViewGroupHandler;
import org.ohosannotations.internal.core.handler.EViewHandler;
import org.ohosannotations.internal.core.handler.EditorActionHandler;
import org.ohosannotations.internal.core.handler.ExtraHandler;
import org.ohosannotations.internal.core.handler.FocusChangeHandler;
import org.ohosannotations.internal.core.handler.FractionArgHandler;
import org.ohosannotations.internal.core.handler.FractionByIdHandler;
import org.ohosannotations.internal.core.handler.FractionByTagHandler;
import org.ohosannotations.internal.core.handler.FromHtmlHandler;
import org.ohosannotations.internal.core.handler.FullscreenHandler;
import org.ohosannotations.internal.core.handler.HierarchyViewerSupportHandler;
import org.ohosannotations.internal.core.handler.HtmlResHandler;
import org.ohosannotations.internal.core.handler.HttpsClientHandler;
import org.ohosannotations.internal.core.handler.IgnoreWhenHandler;
import org.ohosannotations.internal.core.handler.InjectMenuHandler;
import org.ohosannotations.internal.core.handler.InstanceStateHandler;
import org.ohosannotations.internal.core.handler.ItemClickHandler;
import org.ohosannotations.internal.core.handler.ItemLongClickHandler;
import org.ohosannotations.internal.core.handler.ItemSelectHandler;
import org.ohosannotations.internal.core.handler.KeyDownHandler;
import org.ohosannotations.internal.core.handler.KeyLongPressHandler;
import org.ohosannotations.internal.core.handler.KeyMultipleHandler;
import org.ohosannotations.internal.core.handler.KeyUpHandler;
import org.ohosannotations.internal.core.handler.LongClickHandler;
import org.ohosannotations.internal.core.handler.NonConfigurationInstanceHandler;
import org.ohosannotations.internal.core.handler.OnAbilityResultHandler;
import org.ohosannotations.internal.core.handler.PageScrollStateChangedHandler;
import org.ohosannotations.internal.core.handler.PageScrolledHandler;
import org.ohosannotations.internal.core.handler.PageSelectedHandler;
import org.ohosannotations.internal.core.handler.PixelMapResHandler;
import org.ohosannotations.internal.core.handler.PrefHandler;
import org.ohosannotations.internal.core.handler.PreferenceByKeyHandler;
import org.ohosannotations.internal.core.handler.PreferenceChangeHandler;
import org.ohosannotations.internal.core.handler.PreferenceClickHandler;
import org.ohosannotations.internal.core.handler.PreferenceHeadersHandler;
import org.ohosannotations.internal.core.handler.PreferenceScreenHandler;
import org.ohosannotations.internal.core.handler.ReceiverActionHandler;
import org.ohosannotations.internal.core.handler.ReceiverHandler;
import org.ohosannotations.internal.core.handler.RootContextHandler;
import org.ohosannotations.internal.core.handler.RootFragmentHandler;
import org.ohosannotations.internal.core.handler.RunningLockHandler;
import org.ohosannotations.internal.core.handler.ServiceActionHandler;
import org.ohosannotations.internal.core.handler.SharedPrefHandler;
import org.ohosannotations.internal.core.handler.SliderProgressUpdatedHandler;
import org.ohosannotations.internal.core.handler.SliderTouchEndHandler;
import org.ohosannotations.internal.core.handler.SliderTouchStartHandler;
import org.ohosannotations.internal.core.handler.SupposeBackgroundHandler;
import org.ohosannotations.internal.core.handler.SupposeThreadHandler;
import org.ohosannotations.internal.core.handler.SupposeUiThreadHandler;
import org.ohosannotations.internal.core.handler.SystemServiceHandler;
import org.ohosannotations.internal.core.handler.TextUpdatedHandler;
import org.ohosannotations.internal.core.handler.TouchHandler;
import org.ohosannotations.internal.core.handler.TraceHandler;
import org.ohosannotations.internal.core.handler.TransactionalHandler;
import org.ohosannotations.internal.core.handler.UiThreadHandler;
import org.ohosannotations.internal.core.handler.WindowFeatureHandler;
import org.ohosannotations.internal.core.model.OhosRes;
import org.ohosannotations.plugin.OhosAnnotationsPlugin;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * CorePlugin
 *
 * @since 2021-06-02
 */
public class CorePlugin extends OhosAnnotationsPlugin {
    private static final String NAME = "OhosAnnotations";

    @Override
    public String getName() {
        return NAME;
    }

    @Override
    public List<Option> getSupportedOptions() {
        return Arrays.asList(TraceHandler.OPTION_TRACE, SupposeThreadHandler.OPTION_THREAD_CONTROL);
    }

    @Override
    public List<AnnotationHandler<?>> getHandlers(OhosAnnotationsEnvironment annotationEnv) {
        List<AnnotationHandler<?>> annotationHandlers = new ArrayList<>();
        addAnnotation(annotationEnv, annotationHandlers);
        for (OhosRes ohosRes : OhosRes.values()) {
            if (ohosRes == OhosRes.ANIMATION) {
                annotationHandlers.add(new AnimationResHandler(annotationEnv));
            } else if (ohosRes == OhosRes.COLOR) {
                annotationHandlers.add(new ColorResHandler(ohosRes, annotationEnv));
            } else if (ohosRes == OhosRes.COLOR_STATE_LIST) {
                annotationHandlers.add(new ColorStateListResHandler(annotationEnv));
            } else if (ohosRes == OhosRes.PIXEL_MAP) {
                annotationHandlers.add(new PixelMapResHandler(ohosRes, annotationEnv));
            } else if (ohosRes == OhosRes.HTML) {
                annotationHandlers.add(new HtmlResHandler(annotationEnv));
            } else {
                annotationHandlers.add(new DefaultResHandler(ohosRes, annotationEnv));
            }
        }
        addAnnotation2(annotationEnv, annotationHandlers);

        /*
         * WakeLockHandler must be after TraceHandler but before UiThreadHandler and
         * BackgroundHandler
         */
        annotationHandlers.add(new RunningLockHandler(annotationEnv));

        /*
         * UIThreadHandler and BackgroundHandler must be after TraceHandler and
         * IgnoreWhen
         */
        annotationHandlers.add(new UiThreadHandler(annotationEnv));
        annotationHandlers.add(new BackgroundHandler(annotationEnv));

        /*
         * SupposeUiThreadHandler and SupposeBackgroundHandler must be after all
         * handlers that modifies generated method body
         */
        annotationHandlers.add(new SupposeUiThreadHandler(annotationEnv));
        annotationHandlers.add(new SupposeBackgroundHandler(annotationEnv));

        return annotationHandlers;
    }

    private void addAnnotation2(OhosAnnotationsEnvironment annotationEnv,
        List<AnnotationHandler<?>> annotationHandlers) {
        annotationHandlers.add(new TransactionalHandler(annotationEnv));
        annotationHandlers.add(new FractionArgHandler(annotationEnv));
        annotationHandlers.add(new SystemServiceHandler(annotationEnv));
        annotationHandlers.add(new NonConfigurationInstanceHandler(annotationEnv));
        annotationHandlers.add(new AppHandler(annotationEnv));
        annotationHandlers.add(new BeanHandler(annotationEnv));
        annotationHandlers.add(new InjectMenuHandler(annotationEnv));
        annotationHandlers.add(new CustomTitleHandler(annotationEnv));
        annotationHandlers.add(new FullscreenHandler(annotationEnv));
        annotationHandlers.add(new RootContextHandler(annotationEnv));
        annotationHandlers.add(new RootFragmentHandler(annotationEnv));
        annotationHandlers.add(new ExtraHandler(annotationEnv));
        annotationHandlers.add(new BindingObjectHandler(annotationEnv));
        annotationHandlers.add(new TextUpdatedHandler(annotationEnv));
        annotationHandlers.add(new SliderProgressUpdatedHandler(annotationEnv));
        annotationHandlers.add(new SliderTouchStartHandler(annotationEnv));
        annotationHandlers.add(new SliderTouchEndHandler(annotationEnv));
        annotationHandlers.add(new KeyDownHandler(annotationEnv));
        annotationHandlers.add(new KeyLongPressHandler(annotationEnv));
        annotationHandlers.add(new KeyMultipleHandler(annotationEnv));
        annotationHandlers.add(new KeyUpHandler(annotationEnv));
        annotationHandlers.add(new ServiceActionHandler(annotationEnv));
        annotationHandlers.add(new InstanceStateHandler(annotationEnv));
        annotationHandlers.add(new HttpsClientHandler(annotationEnv));
        annotationHandlers.add(new HierarchyViewerSupportHandler(annotationEnv));
        annotationHandlers.add(new WindowFeatureHandler(annotationEnv));
        annotationHandlers.add(new ReceiverHandler(annotationEnv));
        annotationHandlers.add(new ReceiverActionHandler(annotationEnv));
        annotationHandlers.add(new OnAbilityResultHandler(annotationEnv));
        annotationHandlers.add(new PageScrolledHandler(annotationEnv));
        annotationHandlers.add(new PageScrollStateChangedHandler(annotationEnv));
        annotationHandlers.add(new PageSelectedHandler(annotationEnv));
        annotationHandlers.add(new IgnoreWhenHandler(annotationEnv));
        annotationHandlers.add(new AfterInjectHandler(annotationEnv));
        annotationHandlers.add(new AfterExtrasHandler(annotationEnv));
        annotationHandlers.add(new AfterViewsHandler(annotationEnv));
        annotationHandlers.add(new PreferenceScreenHandler(annotationEnv));
        annotationHandlers.add(new PreferenceHeadersHandler(annotationEnv));
        annotationHandlers.add(new PreferenceByKeyHandler(annotationEnv));
        annotationHandlers.add(new PreferenceChangeHandler(annotationEnv));
        annotationHandlers.add(new PreferenceClickHandler(annotationEnv));
        annotationHandlers.add(new AfterPreferencesHandler(annotationEnv));
        annotationHandlers.add(new DataBoundHandler(annotationEnv));

        annotationHandlers.add(new TraceHandler(annotationEnv));
    }

    private void addAnnotation(OhosAnnotationsEnvironment annotationEnv,
        List<AnnotationHandler<?>> annotationHandlers) {
        annotationHandlers.add(new EApplicationHandler(annotationEnv));
        annotationHandlers.add(new EAbilityHandler(annotationEnv));
        annotationHandlers.add(new EProviderHandler(annotationEnv));
        annotationHandlers.add(new EReceiverHandler(annotationEnv));
        annotationHandlers.add(new EServiceHandler(annotationEnv));
        annotationHandlers.add(new EIntentServiceHandler(annotationEnv));
        annotationHandlers.add(new EFractionHandler(annotationEnv));
        annotationHandlers.add(new EBeanHandler(annotationEnv));
        annotationHandlers.add(new EViewGroupHandler(annotationEnv));
        annotationHandlers.add(new EViewHandler(annotationEnv));
        annotationHandlers.add(new SharedPrefHandler(annotationEnv));
        annotationHandlers.add(new PrefHandler(annotationEnv));
        annotationHandlers.add(new ComponentByIdHandler(annotationEnv));
        annotationHandlers.add(new ComponentsByIdHandler(annotationEnv));
        annotationHandlers.add(new FractionByIdHandler(annotationEnv));
        annotationHandlers.add(new FractionByTagHandler(annotationEnv));
        annotationHandlers.add(new FromHtmlHandler(annotationEnv));
        annotationHandlers.add(new ClickHandler(annotationEnv));
        annotationHandlers.add(new LongClickHandler(annotationEnv));
        annotationHandlers.add(new TouchHandler(annotationEnv));
        annotationHandlers.add(new FocusChangeHandler(annotationEnv));
        annotationHandlers.add(new CheckedChangeHandler(annotationEnv));
        annotationHandlers.add(new ItemClickHandler(annotationEnv));
        annotationHandlers.add(new ItemSelectHandler(annotationEnv));
        annotationHandlers.add(new ItemLongClickHandler(annotationEnv));
        annotationHandlers.add(new EditorActionHandler(annotationEnv));
    }
}
